import 'package:m_todo/domain/entity/account_entity.dart';
import 'package:m_todo/domain/service/account_service.dart';
import 'package:m_todo/domain/service/todo_service.dart';
import 'package:m_todo/domain/store/base_todo_store.dart';
import 'package:m_todo/domain/use_case/account_use_case.dart';
import 'package:m_todo/domain/use_case/todo_use_case.dart';
import 'package:m_todo/store/config_file_util.dart';
import 'package:m_todo/store/db_todo_store.dart';
import 'package:m_todo/store/file_account_store.dart';
import 'package:m_todo/store/file_todo_store.dart';

class TodoViewModel {
  final Function(String) printer;
  final Function inputer;

  late TodoUseCase _todoUseCase;

  late AccountUseCase _accountUseCase;

  final ConfigFileUtil _configFileUtil = ConfigFileUtil();

  TodoViewModel(this.printer, this.inputer);

  Future<TodoUseCase> init() async {
    // 账号逻辑
    FileAccountStore accountStore = FileAccountStore();
    _accountUseCase = AccountUseCase(AccountService(accountStore));
    AccountEntity? loginAccount = await _accountUseCase.getLoginAccount();

    // 储存逻辑
    BaseTodoStore todoStore = await _getTodoStore(loginAccount);

    // todoList核心逻辑
    TodoUseCase todoUseCase = TodoUseCase(TodoService(todoStore));

    this._todoUseCase = todoUseCase;
    return todoUseCase;
  }

  Future<BaseTodoStore> _getTodoStore(AccountEntity? loginAccount) async {
    BaseTodoStore todoStore;

    var dbTodoStore = _getDBStore(loginAccount?.name);
    var fileTodoStore = _getFileTodoStore(loginAccount?.name);
    // 支持数据库 &&（初始化数据库成功）
    if (dbTodoStore.support()) {
      if (await dbTodoStore.isEnableDB() || await dbTodoStore.init()) {
        todoStore = dbTodoStore;
        // 如果有该账户文件缓存，把文件导入到数据库，导入成功删除文件
        var fileCache = fileTodoStore.getStoreFile();

        if (await fileCache.exists()) {
          await dbTodoStore.import(fileCache.absolute.path);
          await fileCache.delete();
        }
        return todoStore;
      }
    }
    todoStore = fileTodoStore;
    return todoStore;
  }

  /// 文件储存
  FileTodoStore _getFileTodoStore(String? name) {
    // 根据登录的用户生成todo储存目录
    String dir = './data/';
    String todoFileName = 'todo';

    if (name != null) {
      todoFileName += '_$name';
    }
    return FileTodoStore(dir: dir, todoFileName: todoFileName);
  }

  /// 数据库储存
  DBTodoStore _getDBStore(String? name) {
    return DBTodoStore(name ?? '');
  }

  add(String content) async {
    var todo = await _todoUseCase.add(content);
    p('${todo.index}.${todo.content}');
    p('Item ${todo.index} added');
  }

  done(int index) async {
    try {
      await _todoUseCase.done(index);
    } catch (e) {
      p(e.toString());
      return;
    }

    p('Item $index done');
  }

  getUnDoneList() async {
    var todoList = await _todoUseCase.getUnDoneList();
    p('\n');

    todoList.forEach((todo) {
      p('${todo.index}.${todo.content}');
    });

    p('\n');
    p('Total: ${todoList.length} items');
  }

  getAllList() async {
    var todoList = await _todoUseCase.getAllList();
    p('\n');

    int doneCount = 0;
    todoList.forEach((todo) {
      var state = '';
      if (todo.isDone()) {
        doneCount += 1;
        state = '[Done]';
      }
      p('${todo.index}.$state${todo.content}');
    });

    p('\n');
    p('Total: ${todoList.length} items，$doneCount item done');
  }

  export(String targetPath) async {
    try {
      var absPath = await _todoUseCase.export(targetPath);
      p('导出完成：\n $absPath');
    } catch (e) {
      p('导出异常：\n ${e.toString()}');
    }
  }

  import(String targetFilePath) async {
    try {
      var count = await _todoUseCase.import(targetFilePath);
      p('导出完成：\n 导入 $count 项');
    } catch (e) {
      p('导入异常：\n ${e.toString()}');
    }
  }

  login(String name) async {
    p('请输入密码：');
    String password = inputer.call();
    var result = await _accountUseCase.login(name, password);
    if (result == LoginState.success) {
      p('Login success!');
    }
    if (result == LoginState.invalidPassword) {
      p('密码错误');
    }
    if (result == LoginState.invalidUserName) {
      p('没有该用户');
    }
    if (result == LoginState.repeatLogin) {
      p('已登录，如需切换账户先执行【logout】');
    }
    if (result == LoginState.sysErr) {
      p('程序错误 sorry');
    }
  }

  logout() async {
    await _accountUseCase.logout();
    p('Logout success!');
  }

  configPath() async {
    _configFileUtil.getPath().then((path) => p(path));
  }

  p(String text) {
    printer.call(text);
  }
}
